﻿using Cysharp.Threading.Tasks;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 对象池管理器
/// </summary>
public class PoolManager
{
    private static Dictionary<string, dynamic> s_Pools = new Dictionary<string, dynamic>();
    private static HashSet<string> s_LoadingKeys = new HashSet<string>();

    /// <summary>
    /// 异步生成
    /// </summary>
    public static async UniTask<T> SpawnAsync<T>(string assetName) where T : Component
    {
        // 已缓存，则直接取出
        if (!s_Pools.TryGetValue(assetName, out var pool))
        {
            GameObject prefab = null;
            // 正在加载，则等待其加载完毕，再直接从缓存中读取
            if (s_LoadingKeys.Contains(assetName))
            {
                await UniTask.WaitUntil(() => !s_LoadingKeys.Contains(assetName));
                prefab = await AssetManager.LoadAsync<GameObject>(assetName);
            }
            // 未缓存，则加入缓存列表，等待缓存结束后取出
            else
            {
                s_LoadingKeys.Add(assetName);
                prefab = await AssetManager.LoadAsync<GameObject>(assetName);
                s_LoadingKeys.Remove(assetName);
            }
            pool = new ObjectPool<T>(prefab);
            s_Pools.Add(assetName, pool);
        }
        return (pool as ObjectPool<T>).Rent();
    }

    /// <summary>
    /// 同步生成
    /// </summary>
    public static T Spawn<T>(string assetKey) where T : Component
    {
        // 已缓存，则直接取出
        if (!s_Pools.TryGetValue(assetKey, out var pool))
        {
            var prefab = AssetManager.Load<GameObject>(assetKey);
            pool = new ObjectPool<T>(prefab);
            s_Pools.Add(assetKey, pool);
        }
        return (pool as ObjectPool<T>).Rent();
    }

    /// <summary>
    /// 归还
    /// </summary>
    public static void Despawn<T>(string assetKey, T entity) where T : Component
    {
        if (!s_Pools.TryGetValue(assetKey, out var pool))
            return;
        (pool as ObjectPool<T>).Return(entity);
    }
}